home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / misc / sci / RARS_Amiga_3.lha / RARS / ramdu.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-27  |  13.9 KB  |  370 lines

  1. // RAMDU.CPP for fourmile.trk
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <math.h>
  5. #include "car.h"
  6.  
  7. #include <stdio.h>
  8.  
  9. #define min(x,y) (((x)>(y))?(y):(x))
  10. #define max(x,y) (((x)<(y))?(y):(x))
  11. #define fabs(x) (((x)<0.0)?(-1.0*(x)):(x))
  12. #define sign_turn(rad) (((rad) < 0.0) ? (-1.0) : (1.0))
  13. #define can_decelerate(dist, inv_spd, spd, corn_spd) ((decel_const*(dist)*20.0*(inv_spd)) > ((spd) - (corn_spd))) 
  14.  
  15. #define PI_34 2.3561944
  16. #define PI_2 1.57079632679489661923
  17. #define PI_4 0.7853981
  18. #define PI_1_2 0.6366197
  19. #define PI_1 0.3183098
  20. #define SPEED_CORN 2.0
  21. #define SPEED_CORN2 3.0
  22. #define DIST_CORN  180.0
  23. #define SHORT_CORN (PI*0.5)
  24. #define SHORT_CORN_POWER 3.0
  25. #define ACCEL_CORN (PI/3.0)
  26. #define CORN_POWER 0.5
  27. #define steer_gain  .18
  28.  
  29. extern const double CARWID;
  30.  
  31. double r_fusion(double value1, double value2, double length, double to_end);
  32. double r_adj_alpha(double alpha, double speed, double corn_speed);
  33. double r_get_alpha(double to_inside, double to_outside, double width);
  34. double r_accel_corn(double corn_spd, double len_rad, double len_ft, double nex_rad, double after_rad);
  35.  
  36. static  double  corn_con    =   5.872933    ;
  37. static  double  decel_const =   2.657731    ;
  38. static  double  dist_next_width =   1.287285    ;
  39. static  double  dist_next_inside    =   0.810238    ;
  40. static  double  corn1   =   1.123118    ;
  41. static  double  corn2   =   1.092294    ;
  42. static  double  corn3   =   1.454545    ;
  43. static  double  corn4   =   0.673542    ;
  44. static  double  corn5   =   0.930702    ;
  45. static  double  corn6   =   1.194024    ;
  46. static  double  fusion_pow  =   2.538256    ;
  47. static  double  adj_alpha_pow   =   1.159872    ;
  48. static  double  short_corn  =   2.419606    ;
  49. static  double  short_corn_power    =   4.01663 ;
  50. static  double  speed_corn  =   1.236311    ;
  51. static  double  speed_corn2 =   0.248649    ;
  52. static  double  dist_corn   =   600 ;
  53. static  double  accel_corn  =   0.516688    ;
  54. static  double  drift_corn  =   0.725493    ;
  55. static  double  drift_inside    =   0.003791    ;
  56. static  double  drift_inside_mult   =   1.483808    ;
  57. static  double  corn_mult   =   5.053316    ;
  58. static  double  corn_inside_mult    =   1.391028    ;
  59. static  double  corn_outside_mult   =   0.188757    ;
  60.                                                          
  61. con_vec Ramdu(situation& s)
  62. {
  63.    const char name[] = "Ramdu";
  64.    static int init_flag = 1;
  65.    con_vec result;
  66.    double alpha, vc;
  67.    double Accel_vc;
  68.    double width;                      // track width, feet
  69.    double cur_vel;                    // current velocity
  70.    double inv_spd;                    // 1/s.v
  71.    double cur_length;                    // current length in feet
  72.    double nex_length;                    // current length in feet
  73.    double nex_len;                    // next radius
  74.    double nex_alpha;                  // alpha we'll need on the next turn
  75.    double dist_from_inside;           // distance from inside of turn
  76.    double cur_dist_from_inside;           // distance from inside of turn
  77.    double cur_dist_from_outside;           // distance from inside of turn
  78.    double nex_dist_from_inside;           // distance from inside of turn
  79.    double nex_dist_from_outside;           // distance from inside of turn
  80.    double dist_to_end;           // distance from inside of turn
  81.    double dist_start_next;           // distance from inside of turn
  82.    double nex_corn_spd;               // speed for next corner
  83.    double tmp_corn_spd;               // speed for next corner
  84.    double drift_to;               // speed for next corner
  85.    static double drift_to_mult;               // speed for next corner
  86.    static double drift_to_spot;               // speed for next corner
  87.    static double width_mult;
  88.  
  89.    int same_turn;
  90.    const double slow_same_turn = 0.95;
  91.    const double min_corn_spd = 40.0;
  92.    const double steer_damp = .48;
  93.    static double corn_spd = 65.0;
  94.    static double acc_const = 5000.0;
  95.    static int max_accel = 0;
  96. //   FILE *fp;
  97.  
  98.  
  99.    if(init_flag)  {
  100.       my_name_is(name);
  101.       init_flag = 0;
  102.       result.alpha = result.vc = 0;
  103.       return result;
  104.    }
  105.  
  106.    if(stuck(s.backward, s.v, s.vn, s.to_lft, s.to_rgt, &result.alpha, &result.vc))
  107.       return result;
  108.  
  109.    width = s.to_lft + s.to_rgt;                        // find width of track
  110.    if (s.starting) {
  111.       drift_to_mult = 1.0 / (width * 10.0);
  112.       width_mult = width/120.0;
  113.       width_mult *= width_mult;
  114.  
  115.       // Modifiers to try and handle most tracks
  116.       decel_const += (125.0 - width)/125.0;
  117.       corn_con += (sqrt(width/125.0) - 1.0);
  118.  
  119. /*
  120.    fp = fopen("gene.txt", "rt");
  121.    fscanf(fp, "%lf %lf %lf %lf ", &corn_con, &decel_const, &dist_next_width, &dist_next_inside);
  122.    fscanf(fp, "%lf %lf %lf %lf %lf %lf", &corn1, &corn2, &corn3, &corn4, &corn5, &corn6);
  123.    fscanf(fp, "%lf %lf %lf %lf ", &fusion_pow, &adj_alpha_pow, &short_corn, &short_corn_power);
  124.    fscanf(fp, "%lf %lf %lf %lf ", &speed_corn, &speed_corn2, &dist_corn, &accel_corn);
  125.    fscanf(fp, "%lf %lf %lf ", &drift_corn, &drift_inside, &drift_inside_mult);
  126.    fscanf(fp, "%lf %lf %lf ", &corn_mult, &corn_inside_mult, &corn_outside_mult);
  127.    fclose(fp);
  128. */
  129.    }
  130.  
  131.    /*************************************/
  132.    /* First calculate some basic values */
  133.    /*************************************/
  134.    cur_vel = sqrt(s.v * s.v + s.vn * s.vn);
  135.    if (((s.cur_rad < 0.0) && (s.nex_rad < 0.0)) || 
  136.         ((s.cur_rad > 0.0) && (s.nex_rad > 0.0))) 
  137.             same_turn = 1;
  138.    else
  139.         same_turn = 0;
  140.    if ((s.nex_rad > 0.0) || (((s.nex_rad == 0.0) || (fabs(s.nex_rad) > 2500.0)) && (s.after_rad > 0.0))) {
  141.       nex_dist_from_inside = s.to_lft;
  142.       nex_dist_from_outside = s.to_rgt;
  143.    }
  144.    else if ((s.nex_rad < 0.0) || (((s.nex_rad == 0.0) || (fabs(s.nex_rad) > 2500.0)) && (s.after_rad < 0.0))) {
  145.       nex_dist_from_inside = s.to_rgt;
  146.       nex_dist_from_outside = s.to_lft;
  147.    }
  148.    if (s.cur_rad > 0.0) {
  149.       cur_dist_from_inside = s.to_lft;
  150.       cur_dist_from_outside = s.to_rgt;
  151.    }
  152.    else if (s.cur_rad < 0.0) {
  153.       cur_dist_from_inside = s.to_rgt;
  154.       cur_dist_from_outside = s.to_lft;
  155.    }
  156.    else {
  157.       cur_dist_from_inside = nex_dist_from_inside;
  158.       cur_dist_from_outside = nex_dist_from_outside;
  159.    }
  160.    //cur_length = (fabs(s.cur_rad) + width*0.5) * s.cur_len;
  161.    //nex_length = (fabs(s.nex_rad) + width*0.5) * s.nex_len;
  162.    cur_length = (fabs(s.cur_rad) + cur_dist_from_inside) * s.cur_len;
  163.    nex_length = (fabs(s.nex_rad) + nex_dist_from_inside) * s.nex_len;
  164.  
  165.  
  166.    /*****************************************************************/
  167.    /* Calculate the cornering speeds for this, and the next corners */
  168.    /*****************************************************************/
  169.    corn_spd = 350.0;
  170.    nex_corn_spd = 350.0;
  171.    if ((s.cur_rad == 0.0) || (fabs(s.cur_rad) > 2500.0)) { 
  172.    if (fabs(s.cur_rad) > 2500.0)
  173.       dist_to_end = s.to_end * (fabs(s.cur_rad) + (cur_dist_from_inside));
  174.    else
  175.       dist_to_end = s.to_end;
  176.       if (s.nex_rad != 0.0) {
  177.         corn_spd = max(min_corn_spd, corn_con * pow(fabs(s.nex_rad), CORN_POWER));
  178.         nex_len = s.nex_len;
  179.    if (((s.nex_rad < 0.0) && (s.after_rad < 0.0)) || 
  180.         ((s.nex_rad > 0.0) && (s.after_rad > 0.0))) 
  181.          nex_len *= 2.0;
  182.         corn_spd = r_accel_corn(corn_spd, nex_len, nex_length, s.nex_rad, s.after_rad);
  183.       }
  184.       if ((s.after_rad != 0.0) && (s.after_rad < 2500.0)) {
  185.         nex_corn_spd = max(min_corn_spd, corn_con * pow(fabs(s.after_rad), CORN_POWER));
  186.       }
  187.    }
  188.    else { 
  189.       dist_to_end = s.to_end * (fabs(s.cur_rad) + (cur_dist_from_inside));
  190.       corn_spd = max(min_corn_spd, corn_con * pow(fabs(s.cur_rad), CORN_POWER));
  191.  
  192.       corn_spd = r_accel_corn(corn_spd, s.cur_len, cur_length, s.cur_rad, s.nex_rad);
  193.  
  194.       if (same_turn) 
  195.           corn_spd *= slow_same_turn;
  196.  
  197.       if ((s.nex_rad != 0.0) && (s.nex_rad < 2500.0)) {
  198.         nex_corn_spd = max(min_corn_spd, corn_con * pow(fabs(s.nex_rad), CORN_POWER));
  199.         nex_corn_spd = r_accel_corn(nex_corn_spd, s.nex_len, nex_length, s.nex_rad, s.after_rad);
  200.       }
  201.    }
  202.  
  203.  
  204.  
  205.    // This is to make sure we don't divide by zero
  206.    inv_spd = (s.v < 1e-5 && s.v > -1e-5) ? (1e5) : 1.0/s.v;
  207.  
  208.    /******************************************************************/
  209.    /* Calculate whether we need to change speed for the next segment */
  210.    /******************************************************************/
  211.    Accel_vc = s.v + acc_const * inv_spd;
  212.    if((s.cur_rad == 0.0) || (fabs(s.cur_rad) > 2500.0))         // If we are on a straightaway,
  213.       if((decel_const*dist_to_end*20.0*inv_spd) > (s.v - corn_spd)) { // decel_const is avg deceleration, v*0.05 is avg feet we travel per turn
  214.          vc = Accel_vc;       // keep accelerating near full power
  215.       }
  216.       else  {                 // otherwise,
  217.          vc = ((Accel_vc<corn_spd)? (Accel_vc) : corn_spd);  // decelerate to cornering speed
  218.       }
  219.    else {           // if we're in the curve, maintain speed, +
  220.       if (corn_spd < nex_corn_spd) {
  221.       if ((s.to_end) > accel_corn)
  222.          vc = corn_spd;  // First half of corner, keep corn_spd
  223.       else
  224.          vc = nex_corn_spd;
  225.          if (((s.nex_rad == 0.0) || (fabs(s.nex_rad) > 2500.0)) && (s.after_rad != 0)) {
  226.             // The next straight is so short, let's decelerate to the corner after that.
  227.             tmp_corn_spd = max(min_corn_spd, corn_con * pow(fabs(s.after_rad), CORN_POWER));
  228.             if((decel_const*(dist_to_end+nex_length)*20.0*inv_spd) < (s.v - tmp_corn_spd)) { 
  229.                 vc = tmp_corn_spd;
  230.             }
  231.          }
  232.       }
  233.       else {
  234.       if(((decel_const*dist_to_end*20.0*inv_spd) > (s.v - nex_corn_spd))){ // 1.5 is avg deceleration, v*0.05 is avg feet we travel per turn
  235.          vc = corn_spd;  // First half of corner, keep corn_spd
  236.       }
  237.       else {
  238.          vc = nex_corn_spd;
  239.       }
  240.       }
  241.  
  242.       vc = ((Accel_vc<vc)? (Accel_vc) : vc); // don't accelerate any faster than the max
  243.    }
  244.    if (vc == Accel_vc) max_accel = 1;
  245.    else max_accel = 0;
  246.  
  247.    nex_alpha = 0.0;
  248.    if ((s.nex_rad != 0.0) && (s.nex_rad < 2500.0)) {
  249.     nex_alpha = sign_turn(s.nex_rad) * r_get_alpha(nex_dist_from_inside, nex_dist_from_outside, width);
  250.     if ((s.cur_rad == 0.0) || (fabs(s.cur_rad) > 2500.0))
  251.         nex_alpha = r_adj_alpha(nex_alpha, cur_vel, corn_spd);
  252.     else if (nex_corn_spd > corn_spd)
  253.         nex_alpha = r_adj_alpha(nex_alpha, cur_vel, nex_corn_spd);
  254.    }
  255.    
  256.    if((s.cur_rad == 0.0) || (fabs(s.cur_rad) > 2500.0)) {
  257.       alpha = 0.0;
  258.       //dist_start_next = nex_dist_from_inside;
  259.       dist_start_next = dist_next_width * width + dist_next_inside * nex_dist_from_inside;
  260.  
  261.       if (dist_to_end < dist_start_next) {
  262.           alpha = r_fusion(0.0, nex_alpha, dist_start_next, dist_to_end);
  263.       }
  264.       else if (s.v > 120.0){ // drift
  265.          // Pick our spot for entering the next turn
  266.          drift_to_spot = width * (drift_inside + drift_inside_mult * s.nex_len * PI_1);
  267.  
  268.          // if the next corner is < 90 degrees, drift inside
  269.          drift_to = (s.nex_len < (drift_corn)) ? (CARWID + (drift_to_spot-CARWID)*(s.nex_len* drift_corn)) : (drift_to_spot);
  270.          if ((s.nex_rad != 0.0) && (s.nex_rad < 2500.0)) {
  271.             alpha = sign_turn(s.nex_rad) * (nex_dist_from_inside - drift_to) * drift_to_mult;
  272.          }
  273.       }
  274.  
  275.     }
  276.    else {
  277.       alpha = sign_turn(s.cur_rad) * r_get_alpha(cur_dist_from_inside, cur_dist_from_outside, width);
  278.       alpha = r_adj_alpha(alpha, cur_vel, corn_spd);
  279.  
  280.    if (dist_to_end < 400.0) {
  281.    //dist_start_next = 100.0;
  282.    dist_start_next = 75.0;
  283.    if ((s.cur_rad != 0.0) && (s.cur_len > PI_4))
  284.         dist_start_next += 0.3 * (s.cur_len - PI_4) * fabs(s.cur_rad);
  285.  
  286.    if (fabs(s.cur_rad) < 70.0) {
  287.         if ((s.cur_len < PI_2) && ((s.nex_rad == 0) || (fabs(s.nex_rad) > 2500.0)))
  288.             dist_start_next *= corn1 * (nex_dist_from_inside/width);
  289.         else if ((s.cur_len > PI_34))
  290.             dist_start_next *= corn2 * (nex_dist_from_inside/width);
  291.         else if ((s.cur_len < PI_34) && (s.cur_len > PI_4))
  292.             dist_start_next *= corn3 * (nex_dist_from_inside/width);
  293.    }
  294.    else if ((s.cur_len > PI_34) && ((s.nex_rad != 0.0) || (((s.nex_rad == 0.0) || (fabs(s.nex_rad) > 2500.0)) && (nex_length < 150))))
  295.         dist_start_next *= corn4 * (nex_dist_from_inside/width);
  296.    else if ((s.cur_len < PI_34) && ((s.nex_rad != 0.0) || (((s.nex_rad == 0.0) || (fabs(s.nex_rad) > 2500.0)) && (nex_length < 150))))
  297.         dist_start_next *= corn5 * (nex_dist_from_inside/width);
  298.    else if (cur_length < 125.0)
  299.         dist_start_next *= corn6 * (nex_dist_from_inside/width);
  300.  
  301.    dist_start_next *= width_mult;
  302.    if (dist_to_end < dist_start_next)
  303.         alpha = r_fusion(alpha, nex_alpha, dist_start_next, dist_to_end);  // Scale alpha down to nex_alpha
  304.    }
  305.    }
  306.    alpha -= steer_damp * s.vn * inv_spd;  // This is damping, to prevent oscillation
  307.    // This is a kludge if we're drifting too far outside
  308.    if (cur_dist_from_outside < CARWID)
  309.       alpha *= 4.0;
  310.  
  311.    result.vc = vc;   result.alpha = alpha;
  312.    return result;
  313. }                                                              // v;
  314.  
  315.  
  316. double r_fusion(double value1, double value2, double length, double to_end)
  317. {
  318.     double v1, v2;
  319.     double value = to_end/length;
  320.  
  321.     value = pow(value, fusion_pow);
  322.  
  323.     v1 = value1 * value;
  324.     v2 = value2 * (1.0 - value);
  325.  
  326.     return (v1 + v2);
  327. }
  328.  
  329. double r_adj_alpha(double alpha, double speed, double corn_speed)
  330. {
  331.     double factor = speed/corn_speed;
  332.  
  333.     factor = pow(factor, adj_alpha_pow);
  334.  
  335.     return (alpha * factor);
  336. }
  337.  
  338. double r_get_alpha(double to_inside, double to_outside, double width)
  339. {
  340.    if(to_outside < 1e-5 && to_outside > -1e-5)
  341.       to_outside = .01;
  342.    if (to_inside < (double)CARWID)
  343.     return(steer_gain * -1.0 * (corn_mult * pow((1.0*CARWID - to_inside) / width, corn_inside_mult)  + min(10.0, corn_outside_mult * width/to_outside)));
  344.    else
  345.     return(steer_gain * (corn_mult * pow((to_inside - 1.0*CARWID) / width, corn_inside_mult)  + min(10.0, corn_outside_mult * width/to_outside)));
  346. }
  347.       
  348.  
  349.  
  350. double r_accel_corn(double corn_spd, double len_rad, double len_ft, double nex_rad, double after_rad)
  351. {
  352.  
  353.     if (len_rad < short_corn) {
  354.         corn_spd += corn_spd * speed_corn * pow((short_corn-len_rad)/short_corn, short_corn_power);
  355.         if (len_ft < dist_corn) {
  356.             if (fabs(nex_rad) > 70.0)
  357.                 corn_spd += corn_spd * speed_corn2 * (dist_corn - len_ft)/dist_corn;
  358.             else
  359.                 corn_spd += corn_spd * (0.5 * (fabs(nex_rad))/70.0) * speed_corn2 * (dist_corn - len_ft)/dist_corn;
  360.             if ((after_rad != 0.0) && (after_rad < 2500.0) && 
  361.                 ((nex_rad > 0.0 && after_rad < 0.0) ||
  362.                  (nex_rad < 0.0 && after_rad > 0.0)))
  363.                 corn_spd += corn_spd * 0.5 * (pow((PI_2 - len_rad)/PI_2, 2.0)) * speed_corn2 * (dist_corn - len_ft)/dist_corn;
  364.         }
  365.     }
  366.     return(corn_spd);
  367. }
  368.  
  369.  
  370.